using Microsoft.EntityFrameworkCore;
using net_work.Config;
using net_work.Data.DTO.Appr;
using net_work.Data.Entity.Appr;
using net_work.Data.Enum.Appr;
using net_work.IRepository.Appr;

namespace net_work.Repository.Appr;

public class FlowRepository(ApplicationDbContext dbContext)
    : Repository<Flow>(dbContext), IFlowRepository
{
    public async Task<long> InsertAsync(FlowAddRequest flowAddRequest)
    {
        var newFlow = new Flow
        {
            Remark = flowAddRequest.Remark,
            Name = flowAddRequest.Name,
            Description = flowAddRequest.Description,
            BusinessCode = flowAddRequest.BusinessCode,
            Status = FlowStatus.UnRelease
        };

        await dbContext.Flows.AddAsync(newFlow);
        await dbContext.SaveChangesAsync();
        return newFlow.Id;
    }

    public async Task<bool> UpdateAsync(FlowUpdateRequest flowUpdateRequest)
    {
        var flow = await dbContext.Flows.FindAsync(flowUpdateRequest.Id);
        if (flow == null)
        {
            return false;
        }

        flow.Remark = flowUpdateRequest.Remark;
        flow.Name = flowUpdateRequest.Name;
        flow.Description = flowUpdateRequest.Description;
        flow.BusinessCode = flowUpdateRequest.BusinessCode;
        flow.BeginFlowNodeId = flowUpdateRequest.BeginFlowNodeId;

        await dbContext.SaveChangesAsync();
        return true;
    }

    public async Task<bool> ReleaseFlow(long flowId)
    {
        var flow = await dbContext.Flows.FindAsync(flowId);
        if (flow == null)
        {
            return false;
        }

        flow.Status = FlowStatus.Release;
        return await dbContext.SaveChangesAsync() > 0;
    }

    public async Task<bool> ValidateFlowAsync(long flowId)
    {
        // 1. 检查流程是否存在且开始节点有效
        var flow = await dbContext.Flows
            .Where(f => f.Id == flowId && f.DelFlag == '0')
            .Select(f => f.BeginFlowNodeId)
            .FirstOrDefaultAsync();
        if (flow == null)
        {
            return false; // 开始节点不存在或流程无效
        }

        // 2. 获取该流程的所有节点
        var allNodes = await dbContext.FlowNodes
            .Where(n => n.FlowId == flowId && n.DelFlag == '0')
            .ToListAsync();

        if (allNodes.Count == 0)
        {
            return false; // 流程中没有任何节点
        }

        // 3. 检查节点配置是否完整（包括结束节点也必须配置）
        var incompleteNodes = allNodes
            .Where(n => n.SuccessNodeId == null || n.FailureNodeId == null) // 检查是否有未配置的跳转路径
            .ToList();

        if (incompleteNodes.Count != 0)
        {
            return false; // 存在未配置完整跳转的节点
        }

        // 4. 检查路径连通性（BFS 遍历流程节点）
        var visitedNodes = new HashSet<long>();
        var toVisit = new Queue<long>();
        toVisit.Enqueue(flow.Value); // 从开始节点开始遍历

        var nodeMap = allNodes.ToDictionary(n => n.Id); // 创建节点映射，便于快速查找

        while (toVisit.Count > 0)
        {
            var currentNodeId = toVisit.Dequeue();
            if (!visitedNodes.Add(currentNodeId)) continue; // 如果已访问，跳过

            if (!nodeMap.TryGetValue(currentNodeId, out var currentNode)) continue;

            // 如果成功跳转节点不为 -1，则加入队列
            if (currentNode.SuccessNodeId.HasValue && currentNode.SuccessNodeId != -1)
            {
                toVisit.Enqueue(currentNode.SuccessNodeId.Value);
            }

            // 如果失败跳转节点不为 -1，则加入队列
            if (currentNode.FailureNodeId.HasValue && currentNode.FailureNodeId != -1)
            {
                toVisit.Enqueue(currentNode.FailureNodeId.Value);
            }
        }

        // 5. 检查是否所有节点都被访问
        var unvisitedNodes = allNodes.Select(n => n.Id).Except(visitedNodes).ToList();
        return unvisitedNodes.Count == 0;
    }
}